import os
import argparse
import hashlib

def is_binary_file(file_path):
    """判断是否为二进制文件"""
    with open(file_path, 'rb') as f:
        chunk = f.read(1024)
    return b'\x00' in chunk

def read_file_normalized(file_path):
    """读取文件并统一换行符，尝试多种编码"""
    encodings = ['utf-8', 'gbk', 'gb2312', 'latin-1']
    for encoding in encodings:
        try:
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read()
                return content.replace('\r\n', '\n').replace('\r', '\n').splitlines()
        except UnicodeDecodeError:
            continue
    
    # 编码尝试失败时的兜底处理
    with open(file_path, 'r', encoding='utf-8', errors='replace') as f:
        content = f.read()
        return content.replace('\r\n', '\n').replace('\r', '\n').splitlines()

def count_line_diffs(file1_path, file2_path):
    """计算两个文件的差异行数"""
    if is_binary_file(file1_path) or is_binary_file(file2_path):
        def file_hash(path):
            hash_obj = hashlib.md5()
            with open(path, 'rb') as f:
                while chunk := f.read(4096):
                    hash_obj.update(chunk)
            return hash_obj.hexdigest()
        
        if file_hash(file1_path) != file_hash(file2_path):
            return "二进制文件内容不同"
        return 0

    lines1 = read_file_normalized(file1_path)
    lines2 = read_file_normalized(file2_path)
    
    diff_count = 0
    max_len = max(len(lines1), len(lines2))
    
    for i in range(max_len):
        line1 = lines1[i] if i < len(lines1) else None
        line2 = lines2[i] if i < len(lines2) else None
        
        if line1 != line2:
            diff_count += 1
    
    return diff_count

def compare_directories(dir1, dir2, stats):
    """递归对比目录并更新统计信息"""
    dir1_contents = set(os.listdir(dir1)) if os.path.exists(dir1) else set()
    dir2_contents = set(os.listdir(dir2)) if os.path.exists(dir2) else set()
    
    # 处理共同文件和目录
    for item in sorted(dir1_contents & dir2_contents):
        path1 = os.path.join(dir1, item)
        path2 = os.path.join(dir2, item)
        
        if os.path.isdir(path1) and os.path.isdir(path2):
            # 递归处理子目录
            compare_directories(path1, path2, stats)
        elif os.path.isfile(path1) and os.path.isfile(path2):
            # 统计总文件数
            stats['total_files'] += 1
            # 比较文件差异
            diffs = count_line_diffs(path1, path2)
            if diffs != 0:
                stats['diff_files'] += 1
                # 累加差异行数（二进制文件按1计数）
                if isinstance(diffs, int):
                    stats['total_diff_lines'] += diffs
                else:
                    stats['total_diff_lines'] += 1
                    stats['binary_diff_files'] += 1
                print(f"文件 {path1} 有 {diffs} 行不同")
    
    # 处理仅存在于一个目录的文件
    for item in sorted(dir1_contents - dir2_contents):
        path = os.path.join(dir1, item)
        if os.path.isfile(path):
            stats['total_files'] += 1
            stats['only_in_dir1'] += 1
    
    for item in sorted(dir2_contents - dir1_contents):
        path = os.path.join(dir2, item)
        if os.path.isfile(path):
            stats['total_files'] += 1
            stats['only_in_dir2'] += 1

def main():
    parser = argparse.ArgumentParser(description='统计文件夹对比结果：文件总数、差异数和差异行数')
    parser.add_argument('folder1', help='第一个文件夹路径')
    parser.add_argument('folder2', help='第二个文件夹路径')
    parser.add_argument('--detail', action='store_true', help='显示详细的文件差异信息')
    args = parser.parse_args()
    
    # 验证文件夹路径
    if not os.path.isdir(args.folder1):
        print(f"错误: {args.folder1} 不是有效的文件夹")
        return
    
    if not os.path.isdir(args.folder2):
        print(f"错误: {args.folder2} 不是有效的文件夹")
        return
    
    # 初始化统计数据
    stats = {
        'total_files': 0,           # 总文件数（两边所有文件）
        'diff_files': 0,            # 内容不同的文件数
        'total_diff_lines': 0,      # 累计差异行数
        'binary_diff_files': 0,     # 二进制差异文件数
        'only_in_dir1': 0,          # 仅在第一个文件夹的文件数
        'only_in_dir2': 0           # 仅在第二个文件夹的文件数
    }
    
    print(f"正在对比 {args.folder1} 和 {args.folder2} ...\n")
    compare_directories(args.folder1, args.folder2, stats)
    
    # 输出统计结果
    print("===== 对比统计结果 =====")
    print(f"总文件数量: {stats['total_files']}")
    print(f"仅存在于 {args.folder1} 的文件: {stats['only_in_dir1']}")
    print(f"仅存在于 {args.folder2} 的文件: {stats['only_in_dir2']}")
    print(f"内容不同的文件: {stats['diff_files']}")
    print(f"其中二进制差异文件: {stats['binary_diff_files']}")
    print(f"文本文件累计差异行数: {stats['total_diff_lines']}")

if __name__ == "__main__":
    main()
    